# -*- coding:utf-8 -*-

'''
JOAQUÍN RAMÓN ANTÚNEZ SÁNCHEZ
19 de septiembre de 2014
'''

#from mezzo.mzz import const
from mezzo.mon import jr, reloj


########################################################################################################
## CLASE: const
########################################################################################################
class const:
    TABLA = dict(
                 cd      = 'amadeus.discos', 
                 bach    = 'amadeus.compositores',
                 kleiber = 'amadeus.artistas',
                 fca     = 'amadeus.orquestas',
                 decca   = 'amadeus.discograficas'
                 )
    SQL_DISCO = ('SELECT DISTINCT cd.id as id, cd.titulo as titulo, cd.titulo_interpretacion as titulo_interpretacion, '
                 'cd.volumenes as volumenes, cd.id_etiqueta as id_etiqueta, decca.etiqueta as etiqueta, '
                 'cd.coleccion as coleccion, cd.numero_de_serie as numero_de_serie, cd.edicion as edicion, '
                 'cd.horas as horas, cd.minutos as minutos, cd.segundos as segundos, '
                 'cd.generos as generos\n'
                 'INNER JOIN amadeus.discograficas as decca on cd.id_etiqueta = decca.id\n'
                 'FROM amadeus.discos as cd\n'
                 'ORDER BY titulo, subtitulo, etiqueta, id\n'
                 'LIMIT 0'
                 )
   
########################################################################################################
## CLASE: mzz
########################################################################################################   
class mzz(object):
    def __init__(self, buscame = None, **kwargs):
        self.__id = 0      
        self.__data = kwargs
        self.find(buscame)         
          
    
    def clear(self):
        self.__id = 0
        for key, value in self.__data.items():
            if type(value) is int:
                self.__data[key] = int(0)
            else:
                self.__data[key] = str('')
                
    def add(self):
        if self.__id != 0: return        
        
        keys    = self.__lista_a_cadena( self.__data.keys() ) + ', id'
        valores = str('')         
        for value in self.__data.values():
            if str(value).isdigit():
                valores = '%s%s, ' % (valores, int(value))
            else:
                valores = '%s"%s", ' % (valores, value)
         
        j = jr.instance()
        try:
            x = j.inc('id', const.TABLA[type(self).__name__])
            if x == 0: raise Exception('No se ha obtenido el incremento numérico.\n')            
            
            sql = 'INSERT INTO %s\n(%s)\nVALUES(%s%d)' % ( const.TABLA[type(self).__name__], keys, valores, x )
            j.execute(sql)
            self.__id = x
            
        except Exception as e:
            print e.message
        finally:
            j.close()
            j = None
        
        
    
    def update(self): 
        if self.__id == 0: return
        
        sql = str('')
        for key, value in self.__data.items():
            if str(value).isdigit():
                sql = '%s%s = %s, ' % (sql, key, value)
            else:
                sql = '%s%s = "%s", ' % (sql, key, value)
        
        sql += 'modificado = curdate()\n'
        sql  = 'UPDATE %s set %s where id = %d' % ( const.TABLA[ type(self).__name__ ], sql, self.__id )
        
        j = jr.instance()
        try:
            j.execute(sql)
        except Exception as e:
            print e.message
        finally:
            j.close()
            j = None
        
    
    def __remove(self, sql):
        j = jr.instance()
        try:
            x = j.execute(sql)
            if x != 0: self.clear()
        except Exception as e:
            print e.message
        finally:
            j.close()
            j = None            
    
    def find(self, buscame): 
        if buscame and type(buscame) in [int, str]:
            if type(buscame).__name__ in 'int':
                condicion = 'id = {}'.format(buscame)
            else:
                condicion = self.__condicion(buscame)
            
            sql = ('SELECT DISTINCT %s, id\n'
                   'FROM %s\n'
                   'where %s\n'
                   ) % ( 
                    self.__lista_a_cadena( self.__data.keys() ), 
                   const.TABLA[ type(self).__name__ ], 
                   condicion)
                
            self.clear()       
            j = jr.instance()       
            try:
                row = j.execute(sql)
                if row and row[0]:
                    self.__id = row[0]['id']
                    for key in self.__data.keys():
                        value = row[0][key]
                        if type(value).__name__ in 'int': 
                            self.__data[key] = int( row[0][key] )
                        else:
                            self.__data[key] = str( row[0][key] )
                    
                                      
            except  Exception as e:
                print e.message
            finally:
                j.close()
                j = None              
            
                         
        
    def show(self):
        print 'Número de registro: %s' % ( str(self.__id).zfill(4) )
        for key, value in self.__data.items():
            print key, ':', value
            
    ## ----------------------------------------------------------------------------
    ## PROPIEDADES DE LA CLASE
    ## ----------------------------------------------------------------------------
    def __get_id(self): return int(self.__id)
    id = property( __get_id )         
    
    ## ----------------------------------------------------------------------------
    ## FUNCIONES INTERNAS
    ## ----------------------------------------------------------------------------
    def __lista_a_cadena(self, lista):
        '''Recibo un objeto del tipo lista y devuelvo sus valores separados por
        coma como cadena alfanumérica'''
        caracteres = [ '\'', '{', '}', '[', ']' ]
        for l in caracteres:
            lista = str(lista).replace(l, '')
         
        return lista
    
    def __condicion(self, buscame):
        '''crea la condición empleada en la función de búsqueda "find"'''
        
        tbl = str( type(self).__name__ ).lower().strip()
        if tbl in 'cd':
            return 'LCASE(numero_de_serie) = LCASE("%s")' % (buscame)
        elif tbl in 'decca':
            return 'LCASE(etiqueta) = LCASE("%s")' % (buscame)
        elif tbl in '[bach, kleiber]':
            return (
                    'LCASE( CONCAT_WS(", ",apellidos, nombre) ) = LCASE("%s") OR '
                    'LCASE( CONCAT_WS(" ", nombre, apellidos) = LCASE("%s") )'
                    ) % (buscame, buscame)
        elif tbl in 'fca':
            return (
                    'LCASE(IF(articulo is null or articulo = "", '
                    'nombre, CONCAT_WS(", ", nombre, articulo)  )) = LCASE("%s") OR '
                    'LCASE(IF(articulo is null or articulo = "", '
                    'nombre, CONCAT_WS(" ", articulo, nombre)  )) = LCASE("%s")'
                    ) % (buscame, buscame)

    def __serie_personalizada(self):
        '''Cuando el campo "serie" esté vacio se añadirá a esta función para
        asignar al álbum un número de serie personalizado'''
        t = datetime.today()        
                        
    
    def __codificar(self, value):
        ''' Función interna para upper, title, capitalize'''        
        s = value.strip()
        s = unicode(s, 'utf-8')
        return s    


########################################################################################################
## CLASE: cd
########################################################################################################            

from datetime import date

class cd(mzz):
    
    def __init__(self, buscame = None):
        super(cd, self).__init__(buscame, titulo = '', titulo_interpretacion = '', volumenes = 1,
                                 id_etiqueta = 0, numero_de_serie = '', coleccion = '',
                                 edicion = date.today().year, 
                                 horas = 0, minutos = 0, segundos = 0, generos = 0)        
         
    def clear(self):
        super(cd, self).clear()
        self._mzz__data['volumenes'] = int(1)
        self._mzz__data['edicion'] = date.today().year    
        
    def remove(self):
        sql = (
               'DELETE FROM amadeus.discos where id  = %s AND \n'
               '(SELECT COUNT(id_compositor) from amadeus.compositores_discos where id_disco = %s) = 0 AND '
               '(SELECT COUNT(id_artista) from amadeus.artistas_discos where id_disco = %s) = 0 AND '
               '(SELECT COUNT(id_orquesta) from amadeus.orquestas_discos where id_disco = %s) = 0'
               ) % ( self.id, self.id, self.id, self.id )
        
        self._mzz__remove(sql)                     
        '''    
        j = jr.instance()
        try:
            x = j.execute(sql)
            if x != 0: self.clear()
        except Exception as e:
            print e.message
        finally:
            j.close()
            j = None
       '''             
            
            
    ## ----------------------------------------------------------------------------------------------------
    ## PROPIEDADES
    ## ----------------------------------------------------------------------------------------------------
    def __get_titulo(self): return self._mzz__data['titulo']
    def __set_titulo(self, value): self._mzz__data['titulo'] = value.strip()
    def __get_subtitulo(self): return self._mzz__data['titulo_interpretacion']
    def __set_subtitulo(self, value): self._mzz__data['titulo_interpretacion'] = value.strip()
    
    def __get_volumenes(self): return self._mzz__data['volumenes']
    def __set_volumenes(self, value):        
        if value >= 1 and value <= 75: self._mzz__data['volumenes'] = value
        
    def __get_coleccion(self):
        return self._mzz__data['coleccion'].title().strip()
    def __set_coleccion(self, value): 
        value = unicode(value, 'utf-8')
        self._mzz__data['coleccion'] = value.strip().upper()
        
    def __get_serie(self):     
        return self._mzz__data['numero_de_serie'].strip()
    def __set_serie(self, value): 
        value = unicode(value, 'utf-8')
        self._mzz__data['numero_de_serie'] = value.strip().upper()
        
    def __get_edicion(self):
        value = self._mzz__data['edicion']
        if value <= 0 or value > date.today().year: return ''
        return value
    def __set_edicion(self, value):
        if str(value) == '' or value <= 1950 or value > date.today().year: 
            value = 0    
        self._mzz__data['edicion'] = int(value)    
        
    def __get_generos(self): return int( self._mzz__data['generos'] )
    def __set_generos(self, value):
        if value >= 0 : self._mzz__data['generos'] = int(value)
        
    def __get_tiempo(self): 
        h = int( self._mzz__data['horas'] ) 
        m = int( self._mzz__data['minutos'] )
        s = int( self._mzz__data['segundos'] )
        
        if h == 0 and m == 0 and s == 0: return ''
        
        if h == 0:
            rj = reloj( '%s:%s' % ( str(m).zfill(2), str(s).zfill(2)  ))
        else:                
            rj = reloj( '%s.%s:%s' % ( str(h), str(m).zfill(2), str(s).zfill(2)  ))
            
        return rj.tiempo    
        
    
    def __set_tiempo(self, value): 
        r = reloj(value)
        self._mzz__data['horas']    = r.horas
        self._mzz__data['minutos']  = r.minutos
        self._mzz__data['horas']    = r.segundos
        
        
        
    def __get_etiqueta(self): 
        x = self._mzz__data['id_etiqueta']
        if not x: 
            return None
        else:
            return decca(x)
        
    def __set_etiqueta(self, value): 
        x = 0
        if value: x = value.id             
                
                
    titulo      = property(__get_titulo, __set_titulo)
    subtitulo   = property(__get_subtitulo, __set_subtitulo)    
    volumenes   = property(__get_volumenes, __set_volumenes)
    coleccion   = property(__get_coleccion, __set_coleccion)
    serie       = property(__get_serie, __set_serie)
    edicion     = property(__get_edicion, __set_edicion)    
    generos     = property(__get_generos, __set_generos)
    tiempo      = property(__get_tiempo, __set_tiempo)
    etiqueta    = property(__get_etiqueta, __set_etiqueta)
    


########################################################################################################
## CLASE: fca
########################################################################################################
class fca(mzz):
    def __init__(self, buscame = None):
        super(fca, self).__init__(buscame, nombre = str(''), articulo = str(''))

    def __str__(self):        
        return '%s %s' % ( str(self.id).zfill(3), self.orquesta )
    
    def remove(self):
        sql = (
               'DELETE FROM amadeus.orquestas where id  = %s AND \n'
               '(SELECT COUNT(id_orquesta) from amadeus.orquestas_discos where id_orquesta = %s) = 0'
               ) % ( self.id, self.id, self.id )              
        self._mzz__remove(sql)
         
    
    ## ------------------------------------------------------------------------------------------
    ## Propiedades
    ## -----------------------------------------------------------------------------------------
    def __get_orquesta(self):        
        if len(self._mzz__data['articulo']) == 0:
            return self._mzz__data['nombre'].title()
        else:
            return '%s, %s' % ( self._mzz__data['nombre'].title(), self._mzz__data['articulo'].title() )
    def __set_orquesta(self, value):
        orq = str('')
        art = str('')
        pos = value.find(',')
        if pos == -1:
            orq = unicode(value, 'utf-8')            
        else:
            art = unicode( str(value[pos + 1:]), 'utf-8' )                  
            orq = unicode( str(value[0 : pos]), 'utf-8' )
            
        self._mzz__data['articulo'] = art.strip().upper()
        self._mzz__data['nombre'] = orq.strip().upper()
        
    orquesta = property(__get_orquesta, __set_orquesta)


###################################################################################################
## CLASE: decca
###################################################################################################
class decca(mzz):
    def __init__(self, buscame = None):
        super(decca, self).__init__(buscame, etiqueta = str(''))
        
    def __str__(self):
        return '%s %s' % ( str(self.id).zfill(3), self._mzz__data['etiqueta'] )    
        
    def remove(self):
        sql = (
               'DELETE FROM amadeus.discograficas where id  = %s AND \n'
               '(SELECT COUNT(id_etiqueta) from amadeus.discos where id_etiqueta = %s) = 0'
               ) % ( self.id, self.id, self.id )              
        self._mzz__remove(sql)
        
    
    ## -------------------------------------------------------------------------------------------
    ## Propiedades
    ## -------------------------------------------------------------------------------------------
    def __get_etiqueta(self):
        return self._mzz__data['etiqueta'].title()
    def __set_etiqueta(self, value):
        value = unicode(value, 'utf-8')
        self._mzz__data['etiqueta'] = value.strip().upper()
        
    etiqueta = property(__get_etiqueta, __set_etiqueta)    
                

###################################################################################################
## CLASE: musico (clase "base" para bach y kleiber)
###################################################################################################
class musico(mzz):
    def __init__(self, buscame = None):
        super(musico, self).__init__(buscame, apellidos = str(''), nombre = str(''))    
    
    
    
    ## ---------------------------------------------------------------------------------------------
    ## PROPIEDADES
    ## ---------------------------------------------------------------------------------------------
    def __get_apellidos(self):  return self._mzz__data['apellidos'].title()     
    def __get_nombre(self):     return self._mzz__data['nombre'].title()
    def __set_apellidos(self, value):
        value = unicode(value, 'utf-8')
        self._mzz__data['apellidos'] = value.strip().upper()
    def __set_nombre(self, value):
        value = unicode(value, 'utf-8')
        self._mzz__data['nombre'] = value.strip().upper()    
        
    apellidos   = property(__get_apellidos, __set_apellidos)
    nombre      = property(__get_nombre, __set_nombre)
    
###################################################################################################
## CLASE: bach
###################################################################################################    
class bach(musico):
    def __init__(self, buscame = None):
        super(bach, self).__init__()    
        self._mzz__data['nacimiento'] = int(0)     
        self._mzz__data['muerte'] = int(0)
        if buscame:
            self.find(buscame)
            
    def __str__(self):
        x1 = self._mzz__data['nacimiento']
        x2 = self._mzz__data['muerte']
        edad = str()
        if (x1 > 1500 and x2 > 1500) and (x2 > x1):
            edad = ' (%s-%s)' % (x1, x2)
        else:
            if x1 > 1500: edad = ' (%s)' % (x1)
            
        return '%s %s, %s%s' % (str(self.id).zfill(3), self.apellidos, self.nombre, edad)
    
    def remove(self):
        sql = (
               'DELETE FROM amadeus.compositores where id  = %s AND \n'
               '(SELECT COUNT(id_compositor) from amadeus.compositores_discos where id_compositor = %s) = 0'
               ) % ( self.id, self.id, self.id )              
        self._mzz__remove(sql)    
    
                
    ## --------------------------------------------------------------------------------------------
    ## PROPIEDADES
    ## --------------------------------------------------------------------------------------------
    def __get_nacimiento(self):
        x = self._mzz__data['nacimiento']
        if x > 0 and x < date.today().year: 
            return x
        else:
            return ''
        
    def __get_muerte(self):
        x = int(self._mzz__data['muerte'])
        if x > 0 and x < date.today().year: 
            return x
        else:
            return ''    
        
    def __get_edad(self):
        return
        x1 = int(self.__get_nacimiento())
        x2 = int(self.__get_muerte())
        if x1 > 0 and x2 > 0:
           return (x2 - x1)
        else:
           if x1 > 0:
               return date.today().year - x1
           else:
               return ''
     
    def __set_nacimiento(self, value):
        if value > 1500 and value < date.today().year:
            self._mzz__data['nacimiento'] = int(value)
        else:
            self._mzz__data['nacimiento'] = int(0)
            
    def __set_muerte(self, value):
        if value > 1500 and value < date.today().year:
            self._mzz__data['muerte'] = int(value)
        else:
            self._mzz__data['muerte'] = int(0)         
                          
           
     
    nacimiento  = property(__get_nacimiento, __set_nacimiento)
    muerte      = property(__get_nacimiento, __set_muerte)
    edad        = property(__get_edad)        
            

###################################################################################################
## CLASE: kleiber
###################################################################################################
class kleiber(musico):
    def __str__(self):
        return '%s %s, %s' % (str(self.id).zfill(3), self.apellidos, self.nombre)
    
    def remove(self):
        sql = (
               'DELETE FROM amadeus.artistas where id  = %s AND \n'
               '(SELECT COUNT(id_artista) from amadeus.artistas_discos where id_artista = %s) = 0'
               ) % ( self.id, self.id, self.id )              
        self._mzz__remove(sql)